package com.sunny.springboot2.zk;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;

import java.util.List;

/**
 * @author sunny
 * @date 2019/4/30
 */
public class ZKTest {
    public static void main(String[] args) throws Exception {
        //创建连接
//        CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.226.130:2181", new RetryNTimes(3, 1000));
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString("192.168.226.130:2181")
                .sessionTimeoutMs(30000)
                .connectionTimeoutMs(15000)
                .retryPolicy(new RetryNTimes(3, 3000))
//                .namespace("curatorTest")
                .build();
        //启动zk
        client.start();

        //判断节点是否存在, 存在则删除
        Stat test1Stat = client.checkExists().forPath("/curatorTest/test1");
        if (test1Stat != null) {
            client.delete().guaranteed().deletingChildrenIfNeeded().withVersion(-1).forPath("/curatorTest/test1");
        }

        //创建节点
        client.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                .forPath("/curatorTest/test1", "test1".getBytes());

        // 获取节点信息
        test1Stat = new Stat();
        byte[] test1DataBytes = client.getData().storingStatIn(test1Stat).forPath("/curatorTest/test1");
        System.out.println("test1 stat: " + test1Stat);
        System.out.println("test1 data: " + new String(test1DataBytes));

        // 更新节点数据
        test1Stat = client.setData()
                .withVersion(-1)
                .forPath("/curatorTest/test1", "test1DataV2".getBytes());
        System.out.println("test1 stat: " + test1Stat);

        // 获取所有子节点
        Stat childStat = new Stat();
        List<String> childs = client.getChildren().storingStatIn(childStat).forPath("/curatorTest");
        System.out.println("curatorTest childs: " + childs);

        //        client.delete()
        //                 启用异步执行
        //                .guaranteed()
        //                .withVersion(-1)
        //                .inBackground(((client1, event) -> {
        //                    System.out.println(event.getPath() + ", data=" + event.getData());
        //                    System.out.println("event type=" + event.getType());
        //                    System.out.println("event code=" + event.getResultCode());
        //                }))
        //                .forPath("/curatorTest/test1");

        // 缓存节点     NodeCache只会缓存节点本身的数据和状态，并不会缓存节点下的子节点信息
        NodeCache nodeCache = new NodeCache(client, "/curatorTest/test1");
        nodeCache.start(true);
        // 添加listener
        nodeCache.getListenable().addListener(() -> {
            System.out.println("NodeCache:");
            ChildData childData = nodeCache.getCurrentData();
            if (null != childData) {
                System.out.println("path=" + childData.getPath() + ", data=" + new String(childData.getData()) + ";");
            }
        });


        // 缓存子节点
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/curatorTest", true);
        // startMode为BUILD_INITIAL_CACHE，cache是初始化完成会发送INITIALIZED事件
        pathChildrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
        System.out.println(pathChildrenCache.getCurrentData().size());
        pathChildrenCache.getListenable().addListener(((client1, event) -> {
            ChildData data = event.getData();
            switch (event.getType()) {
                case INITIALIZED:
                    System.out.println("子节点cache初始化完成(StartMode为POST_INITIALIZED_EVENT的情况)");
                    System.out.println("INITIALIZED: " + pathChildrenCache.getCurrentData().size());
                    break;
                case CHILD_ADDED:
                    System.out.println("添加子节点，path=" + data.getPath() + ", data=" + new String(data.getData()));
                    break;
                case CHILD_UPDATED:
                    System.out.println("更新子节点，path=" + data.getPath() + ", data=" + new String(data.getData()));
                    break;
                case CHILD_REMOVED:
                    System.out.println("删除子节点，path=" + data.getPath());
                    break;
                default:
                    System.out.println(event.getType());
            }
        }));

        //分布式锁
        InterProcessMutex mutex = new InterProcessMutex(client, "/lock");
        mutex.acquire();

        // 。。。。 业务逻辑

        mutex.release();

        Thread.sleep(2000);
        client.close();
    }
}
